package com.example.nettydemo.server;

import com.alibaba.fastjson.JSON;
import com.example.nettydemo.config.GameConfig;
import com.example.nettydemo.dto.mock.User;
import com.example.nettydemo.entity.Group;
import com.example.nettydemo.entity.Message;
import com.example.nettydemo.entity.Player;
import com.example.nettydemo.game.Room;
import com.example.nettydemo.service.UserService;
import com.example.nettydemo.service.WalletService;
import com.example.nettydemo.util.MessageUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.net.SocketAddress;

import static com.example.nettydemo.util.Constants.*;

@Component
@ChannelHandler.Sharable
public class NettyHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    @Autowired
    private UserService userService;

    @Autowired
    private WalletService walletService;

    @Autowired
    private GameConfig gameConfig;

    //    @Autowired
//    private Room room;

    //    private String roomId;
    private String guid;


    //接收到客户都发送的消息
    @Override
    public void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        String text = msg.text();
        System.out.println("text = " + text);
        Message message = JSON.parseObject(text, Message.class);
        this.guid = message.getGuid();
        if (this.guid == null) {
            return;
        }
        String roomId = message.getRoomId();
        if (StringUtils.isEmpty(roomId)) {
            roomId = "default";
        }
        Room room = NettyChannelHandlerPool.createOrGetRoom(roomId, gameConfig);
        User user = userService.getOneByGuid(this.guid);
        Message rm = new Message();
        if (user == null) {
            rm.setStatus("error");
            MessageUtil.sendMessageToOne(rm);
            NettyChannelHandlerPool.removeChannel(this.guid);
            return;
        }
        NettyChannelHandlerPool.putChannel(this.guid, ctx.channel().id());
        String type = message.getType();
        if (!"connect".equals(type) && room == null) {
            return;
        }
        rm.setRoomId(roomId);
        switch (type) {
            case "connect":
                //进入房间
                connect(room, user, rm);
                break;
            case "hog":
                //抢庄
                hog(room, message, user, rm);
                break;
            case "pour":
                //下注
                pour(room, message, user, rm);
                break;
            default:
                //暂不支持
                break;
        }
        MessageUtil.sendMessageToOne(rm);
    }

    /**
     * 下注
     *
     * @param room    房间
     * @param message 收到的消息
     * @param user    用户
     * @param rm      返回的消息
     */
    private void pour(Room room, Message message, User user, Message rm) {
        rm.setType("s_pour");
        rm.setGuid(this.guid);
        int status = room.getStatus();
        if (status != STATUS_BETTING) {
            rm.setMsg("当前游戏状态为[" + STATUS_TEXT.get(status) + "]，不能押注！");
            return;
        }
        if (room.getBanker().getGuid().equals(this.guid)) {
            rm.setMsg("你已经抢庄成功，不能押注！");
            return;
        }
        String bet = message.getBet();
        Integer money = message.getMoney();
        Group smallGroup = room.getSmallPlayers();
        Group bigGroup = room.getBigPlayers();
        if ("small".equals(bet)) {
            if (bigGroup.containsPlayer(this.guid)) {
                rm.setMsg("你已经押大了，不能修改！");
                return;
            }
            smallGroup.setBetCount(smallGroup.getBetCount() + 1);
            Player smallPlayer = new Player();
            smallPlayer.setBet(money);
            smallPlayer.setName(user.getUsername());
            smallPlayer.setGuid(this.guid);
            smallGroup.getPlayers().add(smallPlayer);
            room.setSmallPlayers(smallGroup);
            room.setSmallMoney(money + room.getSmallMoney());
        } else {
            if (smallGroup.containsPlayer(this.guid)) {
                rm.setMsg("你已经押小了，不能修改！");
                return;
            }
            bigGroup.setBetCount(bigGroup.getBetCount() + 1);
            Player bigPlayer = new Player();
            bigPlayer.setBet(money);
            bigPlayer.setName(user.getUsername());
            bigPlayer.setGuid(this.guid);
            bigGroup.getPlayers().add(bigPlayer);
            room.setBigPlayers(bigGroup);
            room.setBigMoney(money + room.getBigMoney());
        }
        rm.setMsg("押注操作成功，倒计时结束后公布结果！");
    }

    /**
     * 抢庄
     * @param room 房间
     * @param message 收到的消息
     * @param user 用户
     * @param rm 返回的消息
     */
    private void hog(Room room, Message message, User user, Message rm) {
        rm.setType("s_hog");
        rm.setGuid(this.guid);
//        rm.setRoomId(this.roomId);
        int status = room.getStatus();
        if (status != STATUS_GETTING_BANKER) {
            rm.setMsg("当前游戏状态为[" + STATUS_TEXT.get(status) + "]，不能抢庄！");
            return;
        }
        room.setBankerNum(room.getBankerNum() + 1);
        Player player = new Player();
        player.setGuid(this.guid);
        player.setName(user.getUsername());
        player.setBet(message.getMoney());
        room.setBanker(player);
        rm.setMsg("抢庄操作成功，倒计时结束后公布结果！");
    }

    private void connect(Room room, User user, Message rm) {
        //将玩家添加到房间
        NettyChannelHandlerPool.putRoomGuid(room.getRoomId(), this.guid);
        //进入房间
        rm.setGuid(this.guid);
        rm.setType("connect");
        rm.setStatus("success");
        String username = user.getUsername();
        int balance = walletService.getBalanceByUsername(username);
        rm.setSyncMoney(String.valueOf(balance));
        rm.setMsg(username);
    }

    //客户端建立连接
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        NettyChannelHandlerPool.channelGroup.add(channel);
        SocketAddress socketAddress = channel.remoteAddress();
        System.out.println(socketAddress + "上线了!");
    }

    //关闭连接
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        NettyChannelHandlerPool.channelGroup.remove(ctx.channel());
//        NettyChannelHandlerPool.removeChannel(this.guid);
        System.out.println(ctx.channel().remoteAddress() + "断开连接");
    }

    //出现异常
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
    }


}